#include "EventLoop.h"
#include "CurrentThread.h"
#include "Logger.h"
#include "Poller.h"
#include "Channel.h"

#include <sys/eventfd.h>
#include <unistd.h>
#include <fcntl.h>

// 每个线程都应该有一个自己的eventloop （使用threadlocal技术）
__thread EventLoop *t_loopInThisThread = nullptr;
// 超时时间
const int kPollTimeMs = 10000;

// 调用系统创建fd，目的为mainloop 唤醒 subloop
// 注： muduo库没有采用 生产-消费模式，采用这种唤醒方式直接通知
int createEventfd()
{
    int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (evtfd < 0)
    {
        LOG_FATAL("create event fd error, %d", errno);
    }
    return evtfd;
}

EventLoop::EventLoop()
    : looping_(false), quit_(false), threadId_(CurrentThread::tid()), pollReturnTime_(Timestamp::now()) // 显式初始化Timestamp
      ,
      poller_(Poller::newDefaultPoller(this)), wakeupfd_(createEventfd()), wakeupChannel_(new Channel(this, wakeupfd_)), callingPendingFunctors_(false)

{
    LOG_INFO("EventLoop created in thread %d", threadId_);
    if (t_loopInThisThread)
    {
        LOG_FATAL("another eventloop exist");
    }
    else
    {
        t_loopInThisThread = this;
    }

    // 设置wakeupfd的回调事件
    wakeupChannel_->setReadCallback(std::bind(&EventLoop::handleRead, this));
    // 每一个 eventloop都将监听wakeup的读事件
    wakeupChannel_->enableReading();
};
EventLoop::~EventLoop()
{
    wakeupChannel_->disableAll();
    wakeupChannel_->remove();

    ::close(wakeupfd_);
    t_loopInThisThread = nullptr;
};

void EventLoop::loop() // 开启事件循环
{
    looping_ = true;
    quit_ = false;

    LOG_INFO("event loop %p start loop", this);
    while (!quit_)
    {
        activeCHannels_.clear();
        // 监听的fd有两类，一类是client的fd，一类是wakeupfd（唤醒）
        pollReturnTime_ = poller_->poll(kPollTimeMs, &activeCHannels_);
        for (Channel *channel : activeCHannels_)
        {
            // 通知channel处理相应的事件
            channel->handleEvent(pollReturnTime_);
        }

        // 执行当前eventloop事件循环需要处理的回调操作
        doPendingFunctors();
    }
    LOG_INFO("event loop %p stop loop", this);
    looping_ = false;
}
void EventLoop::quit() // 退出事件循环
{
    quit_ = true;

    // 如果在其他线程调用quit， 需要唤醒，其实就是防止某个线程已经quit_了，但是一直在poll卡住
    if (!isInLoopThread())
    {
        wakeup();
    }
}

void EventLoop::runInLoop(Functor cb) // 在当前loop中执行cb
{
    if (isInLoopThread())
    {
        cb();
    }
    else
    {
        queueInLoop(cb);
    }
}
void EventLoop::queueInLoop(Functor cb) // 将cb放入队列中，唤醒loop所在线程去执行
{
    {
        std::unique_lock<std::mutex> lock(mutex_);
        pendingFunctors_.emplace_back(cb);
    }
    // 唤醒相应的，需要执行上面回调操作的loop的线程
    if (!isInLoopThread() || callingPendingFunctors_)
    {
        wakeup();
    }
    
}



// 调用的poller函数
void EventLoop::updateChannel(Channel *channel)
{
    poller_->updateChannel(channel);
}
void EventLoop::removeChannel(Channel *channel)
{
    poller_->removeChannel(channel);
}
void EventLoop::hasChannel(Channel *channel)
{
    poller_->hasChannel(channel);

}

void EventLoop::doPendingFunctors() // 执行回调
{
    std::vector<Functor> functors;
    callingPendingFunctors_ = true;

    {
        std::unique_lock<std::mutex> lock(mutex_);
        // 不去过度的影响别的线程访问 pendingFunctors_
        functors.swap(pendingFunctors_);
    }
    for(const Functor &functor : functors){
        functor();  // 执行当前loop需要执行的回调
    }

    callingPendingFunctors_ = false;
}

// 唤醒loop所在线程
void EventLoop::wakeup() 
{
    uint64_t one = 1;
    ssize_t n = write(wakeupfd_, &one, sizeof(one));
    if (n != sizeof(one))
    {
        // 读的跟写的对不上 //error（按理来说不可能）
    }
}

/**
 * 函数为读主线程的事件，其实目的为唤醒work线程
 */
void EventLoop::handleRead()
{
    uint64_t one = 1;
    ssize_t n = read(wakeupfd_, &one, sizeof(one));
    if (n != sizeof(one))
    {
        // 读的跟写的对不上 //error（按理来说不可能）
    }
}